#include "RendererGLESCompileConfig.h"

namespace Nezha
{

	GLenum GLenumMapping::BufferUsage(u32 usage)
	{
		switch(usage)
		{
		case HardwareBuffer::HBU_STATIC:
			return GL_STATIC_DRAW;
		case HardwareBuffer::HBU_DYNAMIC:
			return GL_DYNAMIC_DRAW;
		}

		return GL_DYNAMIC_DRAW;
	}

	GLenum GLenumMapping::VertexAttrib(u32 va)
	{
		switch(va)
		{
		case VET_FLOAT1:
		case VET_FLOAT2:
		case VET_FLOAT3:
		case VET_FLOAT4:
			return GL_FLOAT;
		case VET_COLOR:
			return GL_UNSIGNED_BYTE;
		case VET_HALF1:
		case VET_HALF2:
		case VET_HALF3:
		case VET_HALF4:
			// not support in OpenGL ES 2
			 return 0;//GL_HALF_FLOAT_ARB;
		case VET_SHORT1:
		case VET_SHORT2:
		case VET_SHORT3:
		case VET_SHORT4:
			return GL_SHORT;
		}

		return 0;
	}

	GLenum GLenumMapping::GeometryDataType(u32 gdt)
	{
		switch(gdt)
		{
		case POLY_POINT:
			return GL_POINTS;
		case POLY_LINE_SEG:
		case POLY_LINE_OPEN:
			return GL_LINES;
		case POLY_LINE_CLOSED:
			return GL_LINE_STRIP;
		case TRIANGLE_LIST:
			return GL_TRIANGLES;
		case TRIANGLE_STRIP:
			return GL_TRIANGLE_STRIP;
		case TRIANGLE_FAN:
			return GL_TRIANGLE_FAN;
		}

		return 0;
	}

	GLenum GLenumMapping::GLFillMode(RS_FillMode fm)
	{
		switch(fm)
		{
		case RSFM_POINT:
			return GL_POINTS;
		case RSFM_WIREFRAME:
			return GL_LINE_STRIP;
		}

		return 0x1B02;
	}

	GLenum GLenumMapping::GLCompareFunc(RS_CmpMode cmp)
	{
		switch(cmp)
		{
		case RSCM_NEVER:
			return GL_NEVER;
		case RSCM_LESS:
			return GL_LESS;
		case RSCM_LESSEQUAL:
			return GL_LEQUAL;
		case RSCM_EQUAL:
			return GL_EQUAL;
		case RSCM_NOTEQUAL:
			return GL_NOTEQUAL;
		case RSCM_GREATEREQUAL:
			return GL_GEQUAL;
		case RSCM_GREATER:
			return GL_GREATER;
		}

		return GL_ALWAYS;
	}



	GLenum GLenumMapping::GLStencilOp(RS_StencilOP op, bool invert)
	{
		switch(op)
		{
		case RSSOP_ZERO:
			return GL_ZERO;
		case RSSOP_REPLACE:
			return GL_REPLACE;
		case RSSOP_INCREMENT:
			return invert ? GL_DECR : GL_INCR;
		case RSSOP_DECREMENT:
			return invert ? GL_INCR : GL_DECR;
		case RSSOP_INCREMENT_WRAP:
			return invert ? GL_DECR_WRAP : GL_INCR_WRAP;
		case RSSOP_DECREMENT_WRAP:
			return invert ? GL_INCR_WRAP : GL_DECR_WRAP;
		case RSSOP_INVERT:
			return GL_INVERT;
		}

		return RSSOP_KEEP;
	}

	GLenum GLenumMapping::GLBlendFactor(BlendFactor bf)
	{
		switch(bf)
		{
		case BF_ONE:
			return GL_ONE;
		case BF_ZERO:
			return GL_ZERO;
		case BF_DST_COLOR:
			return GL_DST_COLOR;
		case BF_SRC_COLOR:
			return GL_SRC_COLOR;
		case BF_ONE_MINUS_DST_COLOR:
			return GL_ONE_MINUS_DST_COLOR;
		case BF_ONE_MINUS_SRC_COLOR:
			return GL_ONE_MINUS_SRC_COLOR;
		case BF_DST_ALPHA:
			return GL_DST_ALPHA;
		case BF_SRC_ALPHA:
			return GL_SRC_ALPHA;
		case BF_ONE_MINUS_DST_ALPHA:
			return GL_ONE_MINUS_DST_ALPHA;
		case BF_ONE_MINUS_SRC_ALPHA:
			return GL_ONE_MINUS_SRC_ALPHA;
		}

		return GL_ONE;
	}

	GLenum GLenumMapping::GLBlendOp(BlendOperation op)
	{
		switch(op)
		{
		case BO_ADD:
			return GL_FUNC_ADD;
		case BO_SUB:
			return GL_FUNC_SUBTRACT;
		case BO_REVERSE_SUB:
			return GL_FUNC_REVERSE_SUBTRACT;
			// FIXME
//				case BO_MIN:
//#if GL_EXT_blend_minmax
//					return GL_MIN_EXT;
//#endif
//				case BO_MAX:
//#if GL_EXT_blend_minmax
//					return GL_MAX_EXT;
//#endif
		}

		return GL_FUNC_ADD;
	}

	ShaderParamDataType GLenumMapping::ShaderParamType(GLenum glType)
	{
		switch(glType)
		{
		case GL_FLOAT:
			return SPDT_FLOAT;
		case GL_FLOAT_VEC2:
			return SPDT_FLOAT2;
		case GL_FLOAT_VEC3:
			return SPDT_FLOAT3;
		case GL_FLOAT_VEC4:
			return SPDT_FLOAT4;
		case GL_INT:
			return SPDT_INT;
		case GL_INT_VEC2:
			return SPDT_INT2;
		case GL_INT_VEC3:
			return SPDT_INT3;
		case GL_INT_VEC4:
			return SPDT_INT4;
		case GL_FLOAT_MAT2:
			return SPDT_FLOAT2X4;
		case GL_FLOAT_MAT3:
			return SPDT_FLOAT3X4;
		case GL_FLOAT_MAT4:
			return SPDT_FLOAT4X4;
		case GL_SAMPLER_2D:
			return SPDT_SAMPLER_2D;
		case GL_SAMPLER_CUBE:
			return SPDT_SAMPLER_CUBE;
		}

		return SPDT_USER;
	}

	GLenum GLenumMapping::GLTexFormat(TexFormat tf)
	{
		switch(tf)
		{
		case TF_A8:
			{
				return GL_ALPHA;
			}
			break;
				// luminance, 8-bit
		case TF_L8:
		case TF_L16:
			{
				return GL_LUMINANCE;
			}
			break;
		case TF_A4L4:
		case TF_A8L8:
		case TF_GR16:
			{
				return GL_LUMINANCE_ALPHA;
			}
			break;
		case TF_R5G6B5:
		case TF_B5G6R5:
		case TF_RGB16:

				// FIXME half floating-point format
				//// 16-bit floating-point formats
				//TF_R16F,
				//TF_GR16F,
				//TF_RGB16F,
				//TF_RGBA16F,

				//// 32-bit floating-point formats
				//TF_R32F,
				//TF_GR32F,
				//TF_RGB32F,
				//TF_RGBA32F,

				//// DXT compressed formats.
				//TF_DXT1,
				//TF_DXT2,
				//TF_DXT3,
				//TF_DXT4,
				//TF_DXT5,

		case TF_R8G8B8:
		case TF_B8G8R8:
		case TF_PVR_RGB2:
		case TF_PVR_RGB4:
			{
				return GL_RGB;
			}
			break;
		}

		return GL_RGBA;
	}

	GLenum GLenumMapping::GLTexWrap(ShaderSampler::WrapMode wm)
	{
		// fuck GL_CLAMP is not defined.
		switch(wm)
		{
		case ShaderSampler::WM_CLAMP:
			return GL_CLAMP_TO_EDGE;
		case ShaderSampler::WM_WRAP:
			return GL_REPEAT;
		case ShaderSampler::WM_MIRROR:
			return GL_MIRRORED_REPEAT;
		case ShaderSampler::WM_BORDER:
			return GL_CLAMP_TO_EDGE; //GL_CLAMP_TO_BORDER;
		case ShaderSampler::WM_CLAMP_EDGE:
			return GL_CLAMP_TO_EDGE;
		}

		return GL_CLAMP_TO_EDGE;
	}

	GLenum GLenumMapping::GLTexFilter(ShaderSampler::Filter sf)
	{
		switch(sf)
		{
		case ShaderSampler::NEAREST:
			return GL_NEAREST;
		case ShaderSampler::LINEAR:
			return GL_LINEAR;
		case ShaderSampler::NEAREST_MIPMAP_NEAREST:
			return GL_NEAREST_MIPMAP_NEAREST;
		case ShaderSampler::LINEAR_MIPMAP_NEAREST:
			return GL_LINEAR_MIPMAP_NEAREST;
		case ShaderSampler::NEAREST_MIPMAP_LINEAR:
			return GL_LINEAR_MIPMAP_NEAREST;
		case ShaderSampler::LINEAR_MIPMAP_LINEAR:
			return GL_LINEAR_MIPMAP_LINEAR;
		}

		return GL_NEAREST;
	}

}//end namespace Nezha